home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / zcpp_jae.zip / EXCEPTIO.C < prev    next >
C/C++ Source or Header  |  1990-07-06  |  9KB  |  273 lines

  1. /*
  2.  
  3.  
  4.  Copyright (C) 1990 Texas Instruments Incorporated.
  5.  
  6.  Permission is granted to any individual or institution to use, copy, modify,
  7.  and distribute this software, provided that this complete copyright and
  8.  permission notice is maintained, intact, in all copies and supporting
  9.  documentation.
  10.  
  11.  Texas Instruments Incorporated provides this software "as is" without
  12.  express or implied warranty.
  13.  
  14.  
  15.  *
  16.  * Created: MJF 07/05/89 -- Initial design and implementation.
  17.  * Changed: MJF 02/20/90 -- Added group name support.
  18.  *
  19.  * The C++ exception handling defmacro
  20.  *
  21.  * To use, declare:
  22.  *     #pragma defmacro EXCEPTION "exception" exception_g format_msg err_msg
  23.  *                                hprintf delimiter=)
  24.  *
  25.  * where: exception_g is the name of the global variable to use as a temporary,
  26.  *        format_msg is the name of the slot in the exception class, err_msg
  27.  *        is the name of the text package for error message strings, and 
  28.  *        hprintf is  the name of the function which returns a formatted string
  29.  *        from the heap.
  30. */
  31.  
  32. /*
  33.  * EXCEPTION is a cpp macro used to construct an Exception object.
  34.  * EXCEPTION has the following argument options:
  35.  *
  36.  * EXCEPTION(excp_name [, group_names] [, format_string] [rest_args])
  37.  *
  38.  * where   group_names := group_name [, group_names ]
  39.  *           rest_args := rest_arg | [, rest_arg]
  40.  *            rest_arg := format_arg | key_value_slot_arg
  41.  *          format_arg := name
  42.  *  key_value_slot_arg := name = value
  43.  *       format_string := "string"
  44.  *          group_name := SYM(name)
  45.  *          excp_name  := name
  46.  *
  47.  * In general:
  48.  *
  49.  * EXCEPTION(excp_name, SYM(group_name1), SYM(group_name2), format_string, 
  50.  *           key1=val1, arg1, key2=val2, arg2);
  51.  *
  52.  * would generate:
  53.  *
  54.  * (Exception_g = new excp_name(2, SYM(group_name1), SYM(group_name2)), 
  55.  *  Exception_g->format_msg = hprintf(ERR_MSG(format_string), 
  56.  *                                    val1, arg1, val2, arg2),
  57.  *  Exception_g->key1 = val1, 
  58.  *  Exception_g->key2 = val2, 
  59.  *  Exception_g);
  60.  *
  61.  * Note that the value of the key-val-slot-args and the non-key-val-slot-args
  62.  * are all gathered as format args for the hprintf function.  Also note that
  63.  * the key-val-slot-args and the non-key-args are intermixed.  It mainly
  64.  * depends on the format_string requirements.
  65.  *
  66.  * More specific examples using EXCEPTION:
  67.  *
  68.  * (1) EXCEPTION with group_name, error type and format string.
  69.  *
  70.  * EXCEPTION(Error, Serios_Error, "Serious problem here.");
  71.  *
  72.  * would generate:
  73.  *
  74.  *  (Exception_g = new Error(SYM(Serious_Error)), 
  75.  *   Exception_g->format_msg = hprintf(ERR_MSG("Serious problem here.")),
  76.  *   Exception_g);
  77.  *  
  78.  *
  79.  * (2) EXCEPTION with error type, format string and mixture of slot arguments
  80.  *    and format arguments.
  81.  * 
  82.  * Assume a defined error type, Bad_Argment_Error, with two slots, arg_name and 
  83.  * arg_value.
  84.  *
  85.  * Class Bad_Argument_Error : public Fatal {
  86.  * public:
  87.  *  char* arg_name;
  88.  *  int arg_value;
  89.  *  Bad_Argment_Error();
  90.  * }
  91.  *
  92.  * then...
  93.  *
  94.  * EXCEPTION(Bad_Argument_Error, 
  95.  *           "Arg %s has value %d which is out of range for %s."
  96.  *           arg_name="foo", arg_value=x, vec1);
  97.  *
  98.  * would generate...
  99.  *
  100.  *  (Exception_g = new Bad_Argument_Error(),
  101.  *   Exception_g->arg_name = "foo",
  102.  *   Exception_g->arg_value = x,
  103.  *   Exception_g->format_msg =
  104.  *     hprintf(ERR_MSG("Arg %s has value %d which is out of range for %s."),
  105.  *             "foo", x, vec1),
  106.  *   Exception_g);
  107.  *
  108.  * (3) EXCEPTION with error type, and slot arguments (but no format message).
  109.  *
  110.  * Assume a defined error type, Out_Of_Range, with two slots, value and vector.
  111.  * 
  112.  * Class Out_of_Range : public Fatal {
  113.  * public:
  114.  *  int value;
  115.  *  Generic vector;
  116.  *  Out_of_Range() {
  117.  *    format_msg = "Value of %d is out of range for Vector %s."
  118.  *  }
  119.  *  void report(ostream& os) {
  120.  *    os << this->message_prefix();
  121.  *    os << form(format_msg, value, vector);
  122.  *  }
  123.  * };
  124.  *  then...
  125.  *
  126.  *  EXCEPTION(Out_of_Range, value=n, vector=v1);
  127.  *
  128.  *  would generate...
  129.  *
  130.  *  (Exception_g = new Out_of_Range(),
  131.  *   Exception_g->value =  n,
  132.  *   Exception_g->vector = v1,
  133.  *   Exception_g);
  134.  *
  135. */
  136.  
  137. #include "defmacio.h"
  138. #include "macro.h"
  139.  
  140. #define MAXBUF   512
  141. #define MAXGROUP 32
  142.  
  143. exception(argc, argv)
  144.  int argc;
  145.  char* argv[];
  146. {
  147.   char* global_excp;    /* Exception_g */
  148.   char* format_msg;    /* exception format message slot name */
  149.   char* group_fcn;    /* function which updates the group slot */
  150.   char* err_pkg;        /* text package name for error message strings */
  151.   char* format_fcn;    /* hprintf (heap print) function */
  152.   
  153.   char buffer[MAXBUF];
  154.  
  155.   char* macname;    /* EXCEPTION is the macro name */
  156.   char* excp_name;      /* the name of the exception type */
  157.   char* group_names[MAXGROUP];
  158.   int group_count;
  159.   Arg* argp = NULL;    /* always points to first arg in macro */
  160.   Arg* excp_args;    /* EXCEPTION macro arg pointer */
  161.   Arg* fs_args;        /* pointer to format or slot arguments*/
  162.  
  163.   if(argc <= 3) {
  164.     fprintf(stderr, "Not enough arguments to #pragma defmacro exception\n");
  165.     return(1);
  166.   }
  167.   global_excp = argv[1];
  168.   format_msg = argv[2];
  169.   group_fcn = argv[3];
  170.   err_pkg = argv[4];
  171.   format_fcn = argv[5];
  172.  
  173.   copytoken(buffer);        /* Grab the macro name */
  174.   macname = savestring(buffer);
  175.  
  176.   /* Gather all EXCEPTION arguments */
  177.   if((argp = macro_args(macname)) == &arg_error) {  
  178.     fprintf(stderr, ".\n");
  179.     return(1);
  180.   }
  181.  
  182.   /* EXCEPTION takes at least one argument */
  183.   if((excp_args = argp) == NULL) {
  184.     fprintf(stderr, "EXCEPTION: No arguments specified.");
  185.     return(1);
  186.   }
  187.  
  188.   /* first EXCEPTION argument should be name of exception type */
  189.   excp_name = excp_args->name;
  190.   /* call exception constructor */
  191.   sprintf(buffer, "\n(%s = new %s()", global_excp, excp_name);
  192.   puts(buffer);
  193.  
  194.   group_count = 0;
  195.   /* the next EXCEPTION argument might be the optional group names */
  196.   for(excp_args = excp_args->next;
  197.       excp_args !=NULL && excp_args->name[0] != '"' 
  198.       && *excp_args->value == EOS && excp_args->value != NULL;
  199.       excp_args = excp_args->next, group_count++) {
  200.     group_names[group_count] = excp_args->name;
  201.   }
  202.  
  203.   if (group_count == 1) {
  204.     /* only one group name */
  205.     /* output: global_excp->group_fcn(group_name) */
  206.     sprintf(buffer, ",\n%s->%s(%s)", global_excp, group_fcn,
  207.                                      group_names[--group_count]);
  208.     puts(buffer);
  209.   }
  210.  
  211.   if (group_count != 0) {
  212.     /* more than one group name */
  213.     /* output: global_excp->group_fcn(group_count, group_name[0], ...,
  214.                                       ..., group_name[n-1])              */
  215.     sprintf(buffer, ",\n%s->%s(%d", 
  216.                     global_excp, group_fcn, group_count);
  217.     puts(buffer);
  218.     /* output all of the group names */
  219.     while (group_count != 0) {
  220.       sprintf(buffer, ", %s", group_names[--group_count]);
  221.       puts(buffer);
  222.     }
  223.     puts(")");   /* closing paren on group_fcn */
  224.   }
  225.  
  226.   /* the next EXCEPTION argument might be the optional format string */
  227.   if ((excp_args  != NULL) && (excp_args->name[0] == '"')) {
  228.     puts(",\n");
  229.     /* output: global_excp->format_msg = hprintf(err_msg(format_string) ...   */
  230.     sprintf(buffer, "%s->%s = %s(%s(%s)", global_excp, format_msg, format_fcn,
  231.                                       err_pkg, excp_args->name);
  232.     puts(buffer);
  233.     /* output: format_arg1, format_arg2, ...)  */
  234.     excp_args = excp_args->next;   /* skip format string */
  235.     for(fs_args=excp_args;       /* now output each format arg */
  236.         fs_args != NULL;
  237.         fs_args=fs_args->next) {
  238.       puts(", ");
  239.       if (*fs_args->value != EOS)  /* check key=value arg */
  240.     puts(fs_args->value);
  241.       else puts(fs_args->name);
  242.     }
  243.     putchar(')');   /* closing paren for format function, hprintf */
  244.   }
  245.  
  246.   /* the next EXCEPTION argument might be key-value slots */
  247.   for(fs_args = excp_args; fs_args != NULL; fs_args=fs_args->next) {
  248.     if (*fs_args->value != EOS) {
  249.       /* output: global_excp->key = value, */
  250.       puts(",\n");
  251.       sprintf(buffer, "((%s*) %s)->%s = %s", excp_name, global_excp, 
  252.                                          fs_args->name, fs_args->value);
  253.       puts(buffer);
  254.     }
  255.   }
  256.   
  257.   
  258.   /* last output is the global exception name */
  259.   sprintf(buffer, ",\n(%s*) %s)", excp_name, global_excp);
  260.   puts(buffer);
  261.  
  262.   for(argp = argp; argp != NULL;) {
  263.     Arg* old = argp;
  264.     argp = argp->next;
  265.     free(old->name);
  266.     if (*old->value) free(old->value);
  267.     free(old);
  268.   }
  269.   free(macname);
  270.   return 0;
  271. }
  272.  
  273.